<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{margin:0;padding: 0}
        .box{
            width: 100px;
            height: 100px;
            background: red;
        }
        .parent{
            width:1000px;
            height:1000px;
            background: linear-gradient(yellow, green);
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="parent" v-drag="flag">
            <div class="box" v-drag="flag" ></div>
        </div>
    </div>
    <!-- <div data-id="0"  class="box"></div> -->
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    /**
     * 1、实现单元素自由拖拽
     * 2，父子元素都是拖拽元素，点击子元素时只拖拽子元素。
    */

    //Vue.directive 包含Vue可用的指令表,
    /**指令钩子函数会被传入以下参数：
    el：指令所绑定的元素，可以用来直接操作 DOM。
    binding：一个对象，包含以下 property：
        name：指令名，不包括 v- 前缀。
        value：指令的绑定值，例如：v-my-directive="1 + 1" 中，绑定值为 2。
        oldValue：指令绑定的前一个值，仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
        expression：字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中，表达式为 "1 + 1"。
        arg：传给指令的参数，可选。例如 v-my-directive:foo 中，参数为 "foo"。
        modifiers：一个包含修饰符的对象。例如：v-my-directive.foo.bar 中，修饰符对象为 { foo: true, bar: true }。
    vnode：Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
    oldVnode：上一个虚拟节点，仅在 update 和 componentUpdated 钩子中可用
     */
    Vue.directive("drag",(el,{value})=>{
        // console.log(value); //就是获取v-drag的值
        el.style.position = "fixed";
        // console.log(el.Height);//81
        let elX,elY; //拖动对象元素的宽高
        // console.log(el)
        el.addEventListener("mousedown",down);
        
        var disX,disY; //拖动对象元素的最左上角的点在屏幕上的坐标
        function down(e){
            // console.log(e);
            e.cancelBubble = true;
            disX = e.offsetX;
            disY = e.offsetY;
            elX = e.target.offsetWidth;
            elY = e.target.offsetHeight;
            // console.log(elX,elY);
            document.addEventListener("mousemove",move);
            document.addEventListener("mouseup",up)
        }

        function move(e){
              // console.log(e.Target)
            e.cancelBubble=true;
            var l = e.clientX - disX;
            var t = e.clientY - disY;
            if(value){ // value 就是 v-drag 的值
                // 限制可拖动窗口在视口范围内
                if(l < 0 )l=0;
                if(t < 0 )t=0;
                if(l + elX > window.innerWidth ) l = window.innerWidth - elX;
                if(t + elY > window.innerHeight ) t = window.innerHeight - elY;
                el.style.left = l + 'px';
                el.style.top = t + 'px';  
            }
        }

        function up(e){ //传入的事件event对象
            e.cancelBubble=true;
            console.log("我被执行了")
            document.removeEventListener("mousemove",move);
            document.removeEventListener("mouseup",up);
        }
    })



    new Vue({
        el:"#app",
        data:{
            flag:true,
            // msg:"123"
        }
    })
</script>